/**
 * Alibaba.com.cn Inc.
 * Copyright (c) 2004-2021 All Rights Reserved.
 */
package com.smart.helper;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import com.google.common.collect.Lists;
import com.smart.common.enums.ItemTypeEnum;
import com.smart.common.utils.AssertUtil;
import com.smart.mapper.ProjectItemMapper;
import com.smart.mapper.ProjectMapper;
import com.smart.mapper.ProjectReportMapper;
import com.smart.mapper.ProjectTempTaskMapper;
import com.smart.mapper.ProjectWeeklyItemMapper;
import com.smart.mapper.ProjectWeeklyTaskMapper;
import com.smart.mapper.StreetMapper;
import com.smart.model.domain.ProjectDO;
import com.smart.model.domain.ProjectItemDO;
import com.smart.model.domain.ProjectReportDO;
import com.smart.model.domain.ProjectTempTaskDO;
import com.smart.model.domain.ProjectWeeklyItemDO;
import com.smart.model.domain.ProjectWeeklyTaskDO;
import com.smart.model.request.ProjectReportStatisticsRequest;
import com.smart.model.request.ProjectWeeklyTaskRequest;
import com.smart.model.vo.DictItemVO;
import com.smart.model.vo.ProjectReportExportVO;
import com.smart.service.DictItemService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhanghong
 * @version ProjectReportHelper.java, v 0.1 2023/7/19 21:34 下午 ProjectReportHelper Exp $$
 */
@Slf4j
@Component
public class ReportHelper {
    @Autowired
    private ProjectTempTaskMapper projectTempTaskMapper;
    @Autowired
    private ProjectItemMapper projectItemMapper;
    @Autowired
    private CommonUtil commonUtil;
    @Autowired
    private ProjectWeeklyTaskMapper projectWeeklyTaskMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectWeeklyItemMapper projectWeeklyItemMapper;
    @Autowired
    private ProjectReportMapper projectReportMapper;
    @Autowired
    private StreetMapper streetMapper;
    @Autowired
    private DictItemService dictItemService;

    /**
     * 查询指定任务提报数据
     *
     * @param tempTaskId
     * @return
     */
    public ProjectReportExportVO queryExportInfo(Long tempTaskId) {
        // 查询临时任务
        ProjectTempTaskDO taskDO = projectTempTaskMapper.selectDOById(tempTaskId);
        AssertUtil.assertNotNull(taskDO, "非法的临时任务id");

        // 查询该任务下的所有提报数据
        ProjectReportStatisticsRequest param = new ProjectReportStatisticsRequest();
        param.setTaskId(taskDO.getId());
        List<ProjectReportDO> reports = projectReportMapper.listEffectReportByCondition(param);

        //查询填报项,根据优先级排序
        List<String> excelItemType = Lists.newArrayList(ItemTypeEnum.TEXT.name(), ItemTypeEnum.NUMBER.name());
        List<ProjectItemDO> projectItemDOS = projectItemMapper.listByTaskId(taskDO.getId());
        List<ProjectItemDO> excelItemList = projectItemDOS.stream().filter(item -> excelItemType.contains(item.getItemType())).collect(Collectors.toList());
        List<ProjectItemDO> imageItemList = projectItemDOS.stream().filter(item -> Objects.equals(item.getItemType(), ItemTypeEnum.IMAGE.name())).collect(Collectors.toList());

        //处理文件名
        String fileName = String.format("[%s-%s]临时任务提报台账", taskDO.getTaskNum(), taskDO.getName());
        //组装数据
        ProjectReportExportVO vo = new ProjectReportExportVO();
        vo.setFileName(fileName);
        vo.setFileDirPath(String.format("%s_%s", taskDO.getId(), DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN)));

        //处理excel
        if (CollectionUtils.isNotEmpty(excelItemList)) {
            //处理excel表头
            List<String> columns = excelItemList.stream().map(ProjectItemDO::getName).collect(Collectors.toList());
            List<Long> ids = excelItemList.stream().map(ProjectItemDO::getId).collect(Collectors.toList());
            vo.setColumns(columns);

            //处理数据值
            List<List<String>> values = new ArrayList<>();
            List<ProjectDO> projectDOS = new ArrayList<>();
            List<DictItemVO> projectType = dictItemService.queryDictItemByDictCode("PROJECT_TYPE");
            List<DictItemVO> buildType = dictItemService.queryDictItemByDictCode("BUILD_TYPE");
            for (int i = 0; i < reports.size(); i++) {
                List<String> list = commonUtil.buildRow(reports.get(i), ids);
                if (CollectionUtils.isNotEmpty(list)) {
                    values.add(list);
                }
                Long projectId = reports.get(i).getProjectId();
                ProjectDO projectDO = projectMapper.selectDOById(projectId);
                String streetCode = projectDO.getStreetCode();
                String engineeringType = projectDO.getEngineeringType();
                String status = projectDO.getConstructionStatus();
                projectDO.setStreetCode(CommonUtil.streetMap.get(streetCode));
                String dictItemName = projectType.stream().filter(a -> a.getDictItemCode().equals(engineeringType)).findFirst().orElse(new DictItemVO()).getDictItemName();
                String cons = buildType.stream().filter(a -> a.getDictItemCode().equals(status)).findFirst().orElse(new DictItemVO()).getDictItemName();
                projectDO.setEngineeringType(dictItemName);
                projectDO.setConstructionStatus(cons);
                Date startDate = projectDO.getStartDate();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                if (!ObjectUtils.isEmpty(startDate)) {
                    String format = dateFormat.format(startDate);
                    projectDO.setManageOpenStatus(format);
                }
                projectDOS.add(projectDO);
            }
            vo.setValues(values);
            vo.setProjectDOS(projectDOS);
        }

        //处理图片
        if (CollectionUtils.isNotEmpty(imageItemList)) {
            List<Long> ids = imageItemList.stream().map(ProjectItemDO::getId).collect(Collectors.toList());
            List<File> files = reports.parallelStream()
                    .map(item -> commonUtil.buildFiles(item, ids, vo.getFileDirPath()))
                    .filter(Objects::nonNull)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toList());
            vo.setFiles(files);
        }
        return vo;
    }

    /**
     * 查询任务提报数据
     *
     * @param request
     * @return
     */
    public ProjectReportExportVO queryWeeklyExportInfo(ProjectWeeklyTaskRequest request) {
        AssertUtil.assertNotNull(request.getYear(), "年份不能为空");
        AssertUtil.assertNotNull(request.getWeekNum(), "周数不能为空");
        //查询周报任务模板
        ProjectWeeklyTaskDO taskDO = projectWeeklyTaskMapper.queryByYearAndWeek(request.getYear().intValue(), request.getWeekNum().intValue());
        AssertUtil.assertNotNull(taskDO, "未查询到数据");

        //查询填报数据
        List<ProjectReportDO> results = getProjectReportData(request);
        AssertUtil.assertNotEmpty(results, "未查询到数据");

        //查询填报项,根据优先级排序
        List<String> excelItemType = Lists.newArrayList(ItemTypeEnum.TEXT.name(), ItemTypeEnum.NUMBER.name());
        List<ProjectWeeklyItemDO> projectWeeklyItemDOS = projectWeeklyItemMapper.queryWeeklyReportItemByWeeklyId(taskDO.getId());
        List<ProjectWeeklyItemDO> excelItemList = projectWeeklyItemDOS.stream()
                .filter(item -> excelItemType.contains(item.getItemType()))
                .collect(Collectors.toList());
        List<ProjectWeeklyItemDO> imageItemList = projectWeeklyItemDOS.stream()
                .filter(item -> Objects.equals(item.getItemType(), ItemTypeEnum.IMAGE.name()))
                .collect(Collectors.toList());

        //组装数据
        ProjectReportExportVO vo = new ProjectReportExportVO();
        vo.setFileName(getFileName(taskDO));
        vo.setFileDirPath(String.format("%s_%s", taskDO.getId(), DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN)));
        if (CollectionUtils.isNotEmpty(excelItemList)) {
            //处理excel表头
            List<String> columns = excelItemList.stream().map(ProjectWeeklyItemDO::getName).collect(Collectors.toList());
            List<Long> ids = excelItemList.stream().map(ProjectWeeklyItemDO::getId).collect(Collectors.toList());
            vo.setColumns(columns);

            //处理数据值
            List<List<String>> values = new ArrayList<>();
            List<ProjectDO> projectDOS = new ArrayList<>();
            List<DictItemVO> projectType = dictItemService.queryDictItemByDictCode("PROJECT_TYPE");
            List<DictItemVO> buildType = dictItemService.queryDictItemByDictCode("BUILD_TYPE");

            Set<Long> projectIds = results.stream().map(ProjectReportDO::getProjectId).collect(Collectors.toSet());
            Map<Long, ProjectDO> longProjectDOMap = projectMapper.listDOByProjectIds(projectIds);

            for (int i = 0; i < results.size(); i++) {
                List<String> list = commonUtil.buildRow(results.get(i), ids);
                if (CollectionUtils.isNotEmpty(list)) {
                    values.add(list);
                }
                Long projectId = results.get(i).getProjectId();
                //ProjectDO projectDO = projectMapper.selectDOById(projectId);
                ProjectDO projectDO = longProjectDOMap.get(projectId);
                if (projectDO == null) {
                    continue;
                }
                String streetCode = projectDO.getStreetCode();
                String engineeringType = projectDO.getEngineeringType();
                String status = projectDO.getConstructionStatus();

                projectDO.setStreetCode(CommonUtil.streetMap.get(streetCode));
                String dictItemName = projectType.stream()
                        .filter(a -> a.getDictItemCode().equals(engineeringType))
                        .findFirst()
                        .orElse(new DictItemVO())
                        .getDictItemName();
                String cons = buildType.stream().filter(a -> a.getDictItemCode().equals(status)).findFirst().orElse(new DictItemVO()).getDictItemName();
                projectDO.setEngineeringType(dictItemName);
                projectDO.setConstructionStatus(cons);
                if (!ObjectUtils.isEmpty(projectDO.getStartDate())) {
                    projectDO.setManageOpenStatus(DateUtil.format(projectDO.getStartDate(), DatePattern.NORM_DATE_PATTERN));
                }
                projectDOS.add(projectDO);
            }
            vo.setValues(values);
            vo.setProjectDOS(projectDOS);
        }

        //处理图片
        if (CollectionUtils.isNotEmpty(imageItemList)) {
            StopWatch stopWatch = StopWatch.create("download file");
            stopWatch.start();
            log.info("开始下载文件...");
            List<Long> ids = imageItemList.stream().map(ProjectWeeklyItemDO::getId).collect(Collectors.toList());
            List<File> files = results.parallelStream()
                    .map(item -> commonUtil.buildFiles(item, ids, vo.getFileDirPath()))
                    .filter(Objects::nonNull)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toList());

            stopWatch.stop();
            log.info("下载文件完成 总耗时={}s", stopWatch.getTotalTimeSeconds());
            vo.setFiles(files);
        }
        return vo;
    }

    public List<ProjectReportDO> getProjectReportData(ProjectWeeklyTaskRequest request) {
        AssertUtil.assertNotNull(request.getYear(), "年份不能为空");
        AssertUtil.assertNotNull(request.getWeekNum(), "周数不能为空");
        //查询周报任务模板
        ProjectWeeklyTaskDO taskDO = projectWeeklyTaskMapper.queryByYearAndWeek(request.getYear().intValue(), request.getWeekNum().intValue());
        if (taskDO == null) {
            return Collections.emptyList();
        }

        //查询提报数据
        ProjectReportStatisticsRequest req = new ProjectReportStatisticsRequest();
        req.setTaskId(taskDO.getId());
        req.setProjects(request.getProjectIds());
        req.setReportStatus(1);
        req.setStreetCode(request.getStreetCode());
        req.setConstructionStatus(request.getProjectStatus());
        return projectReportMapper.listEffectReportByCondition(req);
    }

    /**
     * 获取文件名
     *
     * @param taskDO
     * @return
     */
    private String getFileName(ProjectWeeklyTaskDO taskDO) {
        String fileNameTemplate = "%s年第%s周(%s~%s)项目周报台账";
        Integer year = taskDO.getYear();
        Integer weekNum = taskDO.getWeekNum();
        String startDate = DateUtil.format(taskDO.getStartTime(), "MM-dd");
        String endDate = DateUtil.format(taskDO.getEndTime(), "MM-dd");

        return String.format(fileNameTemplate, year, weekNum, startDate, endDate);
    }
}
